/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-14 17:38:59
 * @Description  : 用户激活码接口的验证中间件
 */
const Joi = require('joi')
const { Op } = require('sequelize')
const R = require('@/models/Response')
const { UserActiveExam, ActiveCode } = require('@/models/model')
const { ERROR_USER_CODE, ERROR_SYSTEM_CODE } = require('@/constants/errorCode')
const { IS_INTEGER, IS_UNSAFE_INTEGER } = require('@/constants/joiSchema')
const { dumpCheck: globalDumpCheck } = require('@/utils/dumpCheck')

const userActiveExamSchema = {
  userActiveExamIds: Joi.array().items(IS_UNSAFE_INTEGER),
  userActiveExamId: IS_UNSAFE_INTEGER,
  page: IS_INTEGER.min(1).default(1),
  pageSize: IS_INTEGER.min(1).default(999),
  userId: IS_UNSAFE_INTEGER,
  activeCodeId: IS_UNSAFE_INTEGER,
  activeCode: Joi.string(),
  examId: IS_UNSAFE_INTEGER
}

const dumpCheck = {
  /**
   * @author: Hejh(3010733382@qq.com)
   * @description: 验证用户激活码ID的合法性
   * @param {array<string>} userActiveExamIds 用户激活码ID数组
   */
  checkUserActiveExamIds: async (userActiveExamIds) => {
    let newuserActiveExamIds = [...new Set(userActiveExamIds)]
    // 不能出现重复的
    if (newuserActiveExamIds.length !== userActiveExamIds.length) {
      return false
    }

    newuserActiveExamIds = newuserActiveExamIds.map((item) => BigInt(item))

    if (newuserActiveExamIds.length === 0) {
      return true
    }

    // 查看不重复的和数据库的是否对的上
    const myWhere = {
      id: {
        [Op.in]: newuserActiveExamIds
      }
    }
    const userActiveExams = await UserActiveExam.findAll({
      where: myWhere
    })
    if (userActiveExams.length !== newuserActiveExamIds.length) {
      return false
    }

    return true
  }
}

/**
 * @description 用户激活码列表查询的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.listUserActiveExamValidate = async (ctx, next) => {
  const schema = Joi.object({
    page: userActiveExamSchema.page,
    pageSize: userActiveExamSchema.pageSize,
    userId: userActiveExamSchema.userId,
    examId: userActiveExamSchema.examId
  }).validate(ctx.query)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }
  ctx.query = schema.value
  await next()
}

/**
 * @description 创建用户激活码时的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.createUserActiveExamValidate = async (ctx, next) => {
  const schema = Joi.object({
    activeCode: userActiveExamSchema.activeCode.required(),
    examId: userActiveExamSchema.examId.required(),
    userId: userActiveExamSchema.userId
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { examId, activeCode, userId } = ctx.request.body

  const b1 = await globalDumpCheck.checkExamIds([examId])

  const a = await ActiveCode.findOne({
    where: {
      code: activeCode
    }
  })

  if (!a) {
    ctx.body = R.error(ERROR_USER_CODE.ACTIVE_CODE_ID_ERROR)
    return
  }

  if (a.examId !== examId) {
    // 激活码不是当前科目的
    ctx.body = R.error(ERROR_USER_CODE.ACTIVE_CODE_ID_ERROR)
    return
  }

  ctx.request.newBody = {
    examId,
    activeCode,
    activeCodeId: a.id
  }

  // 需要判断激活码是否已被使用
  const one = await UserActiveExam.findOne({
    where: {
      activeCodeId: a.id
    }
  })
  if (one) {
    ctx.body = R.error(ERROR_USER_CODE.USER_ACTIVE_EXAM_USED_ERROR)
    return
  }

  const isActive = await UserActiveExam.findOne({
    where: {
      userId: userId ? userId : ctx.user.id,
      examId
    }
  })
  if (isActive) {
    ctx.body = R.error(ERROR_USER_CODE.USER_ACTIVE_EXAM_ISACTIVE_ERROR)
    return
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除用户激活码接口的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.delUserActiveExamsValidate = async (ctx, next) => {
  const schema = Joi.object({
    userActiveExamIds: userActiveExamSchema.userActiveExamIds.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { userActiveExamIds } = ctx.request.body

  // 验证用户激活码ID数组的合法性
  const b4 = await dumpCheck.checkUserActiveExamIds(userActiveExamIds)
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.USER_ACTIVE_EXAM_ID_ERROR)
    return
  }
  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 用户激活码排序接口的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.sortUserActiveExamsValidate = async (ctx, next) => {
  const schema = Joi.object({
    userActiveExamIds: userActiveExamSchema.userActiveExamIds.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { userActiveExamIds } = ctx.request.body

  // 验证用户激活码ID数组的合法性
  const b4 = await dumpCheck.checkUserActiveExamIds(userActiveExamIds, true)
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.USER_ACTIVE_EXAM_ID_ERROR)
    return
  }

  await next()
}
